package com.hp15c.calculator;

import android.content.Context;
import android.util.Log;
import android.view.Display;
import java.util.Stack;

public class CaculatorMethods {
	
	public Context mContext;
	
	private double TrigFactor = Math.PI / 180;
	private double MAX = 9.999999999e99;
	private double MAX_MAG = 99;
	private int DisplayMode = 1; // 1=FIX 2=SCI 3=ENG
	private int DisplayDigits = 4;
	private boolean StackLift = false;
	private boolean OldStackLift, NewStackLift;
	
	private int A = 0;
	private int B = 1;
	private int C = 2;
	private int D = 3;
	private int E = 4;
	
	private double Stack[]   = {0, 0, 0, 0};
	private double StackI[]  = {0, 0, 0, 0};
	private double  Reg[] = new double[60];
	
	private boolean Running = false;

	private String message;
	
	private int PC = 0;
	private int ReturnStack[];
	private int Program[];
	
	public CaculatorMethods (Context context){
		this.mContext = context;
	}
	
	public double trunc(double x) {
	    if (x < 0) {
	        return -Math.floor(-x);
	    } else {	    	
	        return Math.floor(x);
	    }
	}
	
	public String CalcError(int n) {
		
	    this.message = "Error " + n;
	    Log.i("CaculatorMethods","message = "+message);
	    return message;
	}

	
	public void binop(double f) {
	   
	    if (Double.isNaN(f) || Double.isInfinite(f)) {
	        CalcError(0);
	    }
	    Stack[0] = f;
	}
		
	
	/***********Method for row 1 Start************/
		
	//Can bac 2
	public double sqrt (double x){
		
		Log.i("CaculatorMethods ","sqrt "+Math.sqrt(x));
		return Math.sqrt(x);
	}
	
	// x^2 blue
	public double pow2 (double x){
		Log.i("CaculatorMethods ","pow 2 "+Math.pow(x, 2));	
	
		return Math.pow(x, 2);
	}
	
	//LN case  "e^x" blue
	public double log (double x){
		Log.i("CaculatorMethods ","log "+Math.log(x));
		return Math.log(x);
	}
	
	//LOG case "10^x" blue
	public double log10 (double x){
		Log.i("CaculatorMethods ","LOG "+Math.log10(x));
		return Math.log10(x);
	}
		
	public double expm1(double x){
		Log.i("CaculatorMethods ","e^x - 1 = "+Math.expm1(x));		
		Math.round(x);
		return Math.expm1(x);
	}
	
	/* e = 2.7183  e power x*/
	public double exp(double x){		
		Log.i("CaculatorMethods ","e^x = "+Math.exp(x));
		return Math.exp(x);
	}
	
	public double powy (double x, double y){
		Log.i("CaculatorMethods ","x^y "+Math.pow(x, y));	
		return Math.pow(x, y);
	}
	
	public double abs (double d){
		Log.i("CaculatorMethods ","abs "+Math.abs(d));	
		return Math.abs(d);
	}	
	
	
	//Update number Fix, sci, End
	
	public int log10int(double x) {
		int mag = 0;
		x = Math.abs(x);
	    if (x >= 1) {
	        while (x >= 10) {
	            mag++;
	            x /= 10;
	        }
	    } else if (x > 0) {
	        while (x < 1) {
	            mag--;
	            x *= 10;
	        }
	    }
	    return mag;
	}
	
	public String insert_commas(String s) {
	    String sign = "";
	    if (Character.toString(s.charAt(0)) == "-") {
	        sign =Character.toString(s.charAt(0));
	        s = s.substring(1);
	    }
	    int d = s.indexOf(".");
	    if (d < 0) {
	        d = s.indexOf("e");
	        if (d < 0) {
	            d = s.length();
	        }
	    }
	    while (true) {
	        d -= 3;
	        if (d <= 0) {
	            break;
	        }
	        s = s.substring(0, d) + "," + s.substring(d);
	    }
	    return sign + s;
	}
	
	public void update_display_num(int n){
	
		int dm = 0;
		double x;
		int mag = log10int(n);
		switch (dm) {
        case 1:
            x = Math.round(n * Math.pow(10, DisplayDigits));
            String s = Double.toString(x) ;
            while (s.length() < DisplayDigits+1) {
                s = '0' + s;
            }
            s = s.substring(0, s.length()-DisplayDigits) + '.' + s.substring(s.length()-DisplayDigits);
            s = insert_commas(s);
            break;
        case 2:
        	x = Math.round(n * Math.pow(10, DisplayDigits - mag));
            while (log10int(x) > DisplayDigits) {
                if (mag >= MAX_MAG) {
                    x = Math.floor(n * Math.pow(10, DisplayDigits - mag));
                    break;
                }
                mag++;
                x /= 10;
            }
            s = Double.toString(x);
            while (s.length() < DisplayDigits+1) {
                s = '0' + s;
            }
            s = s.substring(0, 1) + '.' + s.substring(1);
            s += "e" + mag;
            break;
        case 3:
            break;
        }
	}
	
	//fix case 7 yellow
	public void fix(double f) {
		double x;
		x = Math.round(f * Math.pow(10, DisplayDigits));
        String s = Double.toString(x) ;
        while (s.length() < DisplayDigits+1) {
            s = '0' + s;
        }
        s = s.substring(0, s.length()-DisplayDigits) + '.' + s.substring(s.length()-DisplayDigits);
        s = insert_commas(s);
        Log.i("CaculatorMethods","fix = "+s);
	    DisplayDigits = (int) f;
	    StackLift = OldStackLift;
	    
	}
	
	public void op_fix_index() {
	    fix(trunc(Reg['I']));	 
	}
		
	//SCI case 8 yellow
	public void  sci(double f) {
	    DisplayMode = 2;
	    DisplayDigits = (int) f;
	    StackLift = OldStackLift;
	}
	
	public void  op_sci_index() {
	    sci(trunc(Reg['I']));
	}
	
	/* 1/x case blue */
	
	public double op_dpct(double x,double y) {
	    binop((x - y) / y * 100);
	    Log.i("CaculatorMethods","dpct "+(x - y) / y * 100);
	    return (x - y) / y * 100;
	    
	}
	
	/* 1/x case yellow */
	
	/*Case A,B,C*/
	
	public void op_gto_label(int p , int n){
		p = PC + 1;
	    while (true) {	    	
	        if (p >= Program.length) {
	            p = 0;
	        } else 
                break;
	        if (p == PC) {
	           CalcError(4);
	        }
	        p++;
	    }
	    PC = p;		
	}
	
	// Case label is A op_gto_label(11)
	// Case label is B op_gto_label(12)
	// Case label is C op_gto_label(13)
	// Case label is D op_gto_label(14)
	// Case label is E op_gto_label(15)
		
	/**************Method for row 1 END**************/
	
	
	/*********Method for row 2 START*****************/
	public double cos (double x){				
		Log.i("CaculatorMethods ","cos "+Math.cos(x * TrigFactor));		
		return Math.cos(x * TrigFactor);
	}
	
	// Cos - 1 blue 
	public double acos (double x){				
		Log.i("CaculatorMethods ","acos "+Math.acos(x)/ TrigFactor);		
		return Math.acos(x)/ TrigFactor;
	}
	
	public double sin (double x){
		Log.i("CaculatorMethods","sin "+Math.sin(x * TrigFactor));
		return Math.sin(x * TrigFactor);
	}
			
	//sin -1 blue
	public double asin (double x){				
		Log.i("CaculatorMethods ","asin "+Math.asin(x)/ TrigFactor);		
		return Math.asin(x)/ TrigFactor;
	}
	
	public double tan (double x){
		Log.i("CaculatorMethods ","sinh "+Math.tan(x * TrigFactor));
		return Math.tan(x * TrigFactor);
	}
	
	//tan -1 blue
	public double atan (double x){				
		Log.i("CaculatorMethods ","asin "+Math.atan(x)/ TrigFactor);		
		return Math.atan(x)/ TrigFactor;
	}
	
	// sinh, cosh , tanh in case "hyp"
	
	public double sinh (double x){
		Log.i("CaculatorMethods ","sinh "+Math.sinh(x));
		return Math.sinh(x);
	}
	
	public double cosh (double x){
		Log.i("CaculatorMethods ","cosh "+Math.cosh(x));
		return Math.cosh(x);
	}
	
	public double tanh (double x){
		Log.i("CaculatorMethods ","tanh "+Math.cosh(x));
		return Math.tanh(x);
	}
	
	//asinh , acosh, atanh case "hyp-1" blue
	
	public double asinh (double x){
		Log.i("CaculatorMethods ","sinh "+Math.sinh(x));
		return Math.log(x + Math.sqrt(x*x + 1));
	}
	
	public double acosh (double x){
		Log.i("CaculatorMethods ","cosh "+Math.cosh(x));
		return Math.log(x + Math.sqrt(x*x - 1));
	}
	
	public double atanh (double x){
		Log.i("CaculatorMethods ","tanh "+Math.cosh(x));
		return Math.log((1 + x) / (1 - x)) / 2;
	}
	
	/*Method for row 2 END */
	
	public double sum(double x,double y){		
		
		return x+y;
	}
	
	public double div(double x,double y){				
		return x/y;
	}
	
	public double x(double x,double y){				
		return x*y;
	}
	
	public double except(double x,double y){				
		return x-y;
	}	
	
	public void op_rand() {
	    Math.random();
	}

}
